package com.listviewdemo.widget;

import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;

import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.listviewdemo.R;
import com.listviewdemo.event.AddViewEvent;
import com.listviewdemo.event.RefreshChildEvent;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by tzj on 2018/4/25.
 */
@ReactModule(name = RnListViewManager.REACT_CLASS)
public class RnListViewManager extends ViewGroupManager<RnListView> {
    protected static final String REACT_CLASS = "RCTListView";
    private SparseArray<View> mCacheViews = new SparseArray<>();
    private int maxRows = 30;
    private int dividerHeight;
    private boolean isPaddingLeft;
    private boolean isPaddingTop;
    private boolean isPaddingRight;
    private boolean isPaddingBottom;

    private List mData = new ArrayList();
    private EventDispatcher mEventDispatcher;

    @Override
    public String getName() {
        return REACT_CLASS;
    }

    @Override
    protected RnListView createViewInstance(ThemedReactContext reactContext) {
        mEventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
        RnListView rnListView = new RnListView(reactContext);
        rnListView.setClipToPadding(false);
        rnListView.setClipChildren(false);
        rnListView.setHeaderDividersEnabled(true);
        rnListView.setFooterDividersEnabled(true);
        rnListView.setOverScrollMode(View.OVER_SCROLL_NEVER);
        rnListView.setAdapter(mAdapter);
//        Log( "createViewInstance: " );
        return rnListView;
    }

    @Override
    public boolean needsCustomLayoutForChildren() {
        return true;
    }

    @ReactProp(name = "maxRows",defaultInt=30)
    public void setMaxRows(RnListView parent, int max) {
        maxRows = max;
    }
    @ReactProp(name = "isPadding")
    public void isPadding(RnListView parent,  ReadableArray read) {
//        Log( "isPadding: "+read);
        isPaddingLeft = read.getBoolean(0);
        isPaddingTop = read.getBoolean(1);
        isPaddingRight = read.getBoolean(2);
        isPaddingBottom = read.getBoolean(3);
        setDividers(parent,dividerHeight);
    }
    @ReactProp(name = "dividerHeight",defaultInt = 10)
    public void setDividerHeight(RnListView parent, int height) {
//        Log("setDividerHeight: "+height);
        parent.setDividerHeight(height = (int) PixelUtil.toPixelFromDIP(height));
        if(height>0){
            setDividers(parent,height);
        }
    }
    @ReactProp(name = "dividerColor", defaultInt = Color.TRANSPARENT, customType = "Color")
    public void setDivider(RnListView parent, int color) {
//        Log("setDivider: "+color);
        int dividerHeight = parent.getDividerHeight();
        parent.setDivider(new ColorDrawable(color));
        if(dividerHeight>0){
            parent.setDividerHeight(dividerHeight);
            setDividers(parent,dividerHeight);
        }
    }
    private void setDividers(RnListView parent,int height){
        dividerHeight = height;
        int left = parent.getPaddingLeft();
        int top = parent.getPaddingTop();
        int right = parent.getPaddingRight();
        int bottom = parent.getPaddingBottom();
        if(isPaddingLeft){
            left = height;
        }
        if(isPaddingTop){
            top = height;
        }
        if(isPaddingRight){
            right = height;
        }
        if(isPaddingBottom){
            bottom = height;
        }
        parent.setPadding(left,top,right,bottom);
    }

    @ReactProp(name = "selectorColor", defaultInt = Color.TRANSPARENT, customType = "Color")
    public void setSelector(RnListView parent, int color) {
        parent.setSelector(new ColorDrawable(color));
    }
    @ReactProp(name = "data")
    public void setData(RnListView parent, ReadableArray read) {
        mData.clear();
        if (read == null) {
            return;
        } else {
            for (int i = 0; i < read.size(); i++) {
                mData.add(i);
            }
        }
//        Log( "setData: " + read.size() + " mData：" + mData.size());
        notifyDataSetChanged(parent);
    }

    public void notifyDataSetChanged(ListView listView) {
        mAdapter.notifyDataSetChanged();
    }


    //==========================================
    @Override
    public void addView(RnListView parent, View child, int index) {
//        Log( "addView: " + index);
        ViewGroup viewGroup = (ViewGroup) mCacheViews.get(index);
        if (viewGroup != null&&child.getParent()==null&&viewGroup instanceof RnFrameLayout) {
            ((RnFrameLayout)viewGroup).addReactView(child);
//            notifyDataSetChanged(parent);
        } else {
            throw new RuntimeException("请查看外层是否加了View(不加style视为没加) CacheView="+mCacheViews.size()+" index="+index+" ViewGroup="+viewGroup+" Parent="+child.getParent());
        }
    }

    @Override
    public void removeViewAt(RnListView parent, int index) {
//        Log( "removeViewAt: " + index);
        notifyDataSetChanged(parent);
    }

    @Override
    public void removeAllViews(RnListView parent) {
//        Log( "removeAllViews: ");
        mData.clear();
        mCacheViews.clear();
        notifyDataSetChanged(parent);
    }

    private BaseAdapter mAdapter = new BaseAdapter() {
        @Override
        public int getCount() {
            return mData.size();
        }
        @Override
        public Object getItem(int position) {
            return mData.get(position);
        }
        @Override
        public long getItemId(int position) {
            return position;
        }
        @Override
        public View getView(final int position, View convertView, final ViewGroup parent) {
//            Log("getView: convertView=" + convertView + " position=" + position + " cacheViews=" + mCacheViews.size());
            if (convertView == null) {
                if (position < mCacheViews.size()) {
                    convertView = mCacheViews.get(position);
                    if(convertView==null){
                        throw new RuntimeException("position="+position+" ChildCount="+parent.getChildCount()+" CacheView="+mCacheViews.size());
                    }else{
                        eventToRefresh(position,convertView,parent);
                    }
                } else {
                    ViewGroup viewGroup = new RnFrameLayout(parent.getContext());
                    mCacheViews.put(mCacheViews.size(), convertView = viewGroup);
                    convertView.setTag(R.id.react_view_id_tag,mCacheViews.size()-1);
                    if(mCacheViews.size()<maxRows){
                        mEventDispatcher.dispatchEvent(new AddViewEvent(parent.getId(), mCacheViews.size()-1));
                    }
                }
            } else {
                eventToRefresh(position,convertView,parent);
            }
            return convertView;
        }

        /**
         * 这里最好还是 new 个新的Event，因为发现不new 的话滑动过快会报错
         */
        private void eventToRefresh(int position, View convertView, ViewGroup parent){
//            RefreshChildEvent event = (RefreshChildEvent) convertView.getTag(R.id.react_view_event_tag);
//            if(event==null){
                RefreshChildEvent event = new RefreshChildEvent(parent.getId(), (int) convertView.getTag(R.id.react_view_id_tag), position);
//            }else{
//                event.newEvent(parent.getId(), (int) convertView.getTag(R.id.react_view_id_tag), position);
//            }
            mEventDispatcher.dispatchEvent(event);
//            convertView.setTag(R.id.react_view_event_tag,event);
        }
    };

    //================== java 调 js
    @Override
    public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
        return MapBuilder.<String, Object>builder()
                .put(AddViewEvent.NAME, MapBuilder.of("registrationName", "onRenderItem"))
                .put(RefreshChildEvent.NAME, MapBuilder.of("registrationName", "onRefresh"))
                .build();
    }

}
